/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pe.edu.pucp.sigepa.recocidosimulado.capadatos.impl;

import com.mysema.query.jpa.EclipseLinkTemplates;
import com.mysema.query.jpa.impl.JPAQuery;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.javatuples.Pair;
import pe.edu.pucp.sigepa.recocidosimulado.Controlador.AeropuertoJpaController;
import pe.edu.pucp.sigepa.recocidosimulado.Modelo.Aeropuerto;
import pe.edu.pucp.sigepa.recocidosimulado.Modelo.Ciudad;
import pe.edu.pucp.sigepa.recocidosimulado.Modelo.Continente;
import pe.edu.pucp.sigepa.recocidosimulado.Modelo.Pais;
import pe.edu.pucp.sigepa.recocidosimulado.Modelo.QAeropuertoSim;
import pe.edu.pucp.sigepa.recocidosimulado.Modelo.QAvionSim;
import pe.edu.pucp.sigepa.recocidosimulado.Modelo.QPronosticoSim;
import pe.edu.pucp.sigepa.recocidosimulado.Modelo.QTipoAvion;
import pe.edu.pucp.sigepa.recocidosimulado.Modelo.QVueloSim;
import pe.edu.pucp.sigepa.recocidosimulado.Modelo.VueloSim;
import pe.edu.pucp.sigepa.recocidosimulado.capadatos.interfaz.LogicaVuelosSimulacion;
import pe.edu.pucp.sigepa.recocidosimulado.domain.interfaz.ProblemaSim;
import pe.edu.pucp.sigepa.recocidosimulado.domain.interfaz.SolucionSim;


/**
 *
 * @author carloslengua
 */
public class LogicaVuelosSimulacionImpl implements LogicaVuelosSimulacion {
    
    
    @Override
    public Integer obtenerIdContinente(Integer idAeropuerto) {
        
        EntityManagerFactory emf;
        emf = Persistence.createEntityManagerFactory("pe.edu.pucp_motor-generador-rutas-RS2_jar_1.0-SNAPSHOTPU", System.getProperties());
    
        AeropuertoJpaController aeropuertoJpaController = new AeropuertoJpaController(null, emf);
        
        Aeropuerto aeropuerto = aeropuertoJpaController.findAeropuerto(idAeropuerto);
        
        Ciudad ciudad = aeropuerto.getCiudad();
        
        Pais pais = ciudad.getPais();
        
        Continente continente = pais.getContinente();
        
        return continente.getIdcontinente();
    
    }//OK
    
    @Override
    public List<VueloSim> retornarVuelos(Integer idAeropuertoActual, Date fechaHoraSimulacion, Integer nroPaquetes) {
//        Llamada 5, 2012-09-02 08:00:00, 20
//        throw new UnsupportedOperationException("Not supported yet.");
               
        JPAQuery consulta = new JPAQuery(
                                    Persistence.createEntityManagerFactory("pe.edu.pucp_motor-generador-rutas-RS2_jar_1.0-SNAPSHOTPU", System.getProperties())
                                        .createEntityManager(), EclipseLinkTemplates.DEFAULT);
        
        QVueloSim vueloSim = QVueloSim.vueloSim;
        QAvionSim avionSim = QAvionSim.avionSim;
        QTipoAvion tipoAvion = QTipoAvion.tipoAvion;
        QAeropuertoSim aeropuertoSim = QAeropuertoSim.aeropuertoSim;
        QPronosticoSim pronosticoSim = QPronosticoSim.pronosticoSim;
        QPronosticoSim pronosticoSim2 = new QPronosticoSim("pronosticoSim2");
        
        List<VueloSim> vuelosSim = consulta.from(vueloSim)//Pero si la llave foranea es de la tabla AvionSIm
                                .innerJoin(vueloSim.avionSim, avionSim)
                                .innerJoin(avionSim.tipoAvion, tipoAvion)
                                .innerJoin(vueloSim.aeropuertoSimDestino, aeropuertoSim)
                                .where(vueloSim.aeropuertoSimOrigen.idaeropuerto.eq(idAeropuertoActual)
                                        .and(vueloSim.salidaest.after(fechaHoraSimulacion))
                                        .and((vueloSim.numpack.add(nroPaquetes).loe(tipoAvion.cappack))))
//                                        .and(new HibernateSubQuery().from(pronostico)
//                                                .where(pronostico.aeropuerto.eq(vuelo.aeropuertoDestino)
//                                                        .and(pronostico.fechareg.before(fechaHoraSimulacion)))
//                                                .unique(pronostico.nropack.sum()).exists().and(
//                                                    new HibernateSubQuery().from(pronostico2)
//                                                        .where(pronostico2.aeropuerto.eq(vuelo.aeropuertoDestino)
//                                                                .and(pronostico2.fechareg.before(fechaHoraSimulacion)))
//                                                        .unique(pronostico2.nropack.sum()).loe(aeropuerto.cappack.subtract(vuelo.numpack)))))
                                .list(vueloSim);
                
        return vuelosSim;
        
    }
    
    //Obviar escala
    @Override
    public List<VueloSim> obtenerVuelosReemplazantes(ProblemaSim problemaSim, SolucionSim solucionSim, Integer indiceParVuelos) {
//        throw new UnsupportedOperationException("Not supported yet.");

        JPAQuery consulta = new JPAQuery(
                                    Persistence.createEntityManagerFactory("pe.edu.pucp_motor-generador-rutas-RS2_jar_1.0-SNAPSHOTPU", System.getProperties())
                                        .createEntityManager());     
        
        QVueloSim vueloSimX = QVueloSim.vueloSim;
        
        QVueloSim vueloSim0 = new QVueloSim("vueloSim0");
        QVueloSim vueloSim1 = new QVueloSim("vueloSim1");
        QVueloSim vueloSim2 = new QVueloSim("vueloSim2");
        QVueloSim vueloSim3 = new QVueloSim("vueloSim3");        
        
        QAvionSim avionSim = QAvionSim.avionSim;
        QTipoAvion tipoAvion = QTipoAvion.tipoAvion;
        QAeropuertoSim aeropuertoSimOrigen = new QAeropuertoSim("aeropuertoSimOrigen");
        QAeropuertoSim aeropuertoSimDestino = new QAeropuertoSim("aeropuertoSimDestino");
        QPronosticoSim pronosticoSim = QPronosticoSim.pronosticoSim;
        QPronosticoSim pronosticoSim2 = new QPronosticoSim("pronosticoSim2");
        
        Integer idVuelo1 = solucionSim.get(indiceParVuelos).getIdvuelo();
        Integer idVuelo2 = solucionSim.get(indiceParVuelos + 1).getIdvuelo();        
        
        Integer nroPaquetes = problemaSim.getNroPaquetes();
        Date fechaPeticion = problemaSim.getFechaPeticion();
        
        if (0 <= (indiceParVuelos - 1) && (indiceParVuelos + 2) <= solucionSim.size() - 1 ) {
        
            Integer idVuelo0 = solucionSim.get(indiceParVuelos - 1).getIdvuelo();
            Integer idVuelo3 = solucionSim.get(indiceParVuelos + 2).getIdvuelo();
            
            List<VueloSim> vuelosSim = consulta.from(vueloSimX, vueloSim0, vueloSim1, vueloSim2, vueloSim3)
                                    .innerJoin(vueloSimX.avionSim, avionSim)
                                    .innerJoin(avionSim.tipoAvion, tipoAvion)
                                    .innerJoin(vueloSimX.aeropuertoSimOrigen, aeropuertoSimOrigen)
                                    .innerJoin(vueloSimX.aeropuertoSimDestino, aeropuertoSimDestino)
                                        .where(vueloSim0.idvuelo.eq(idVuelo0)
                                            .and(vueloSim1.idvuelo.eq(idVuelo1))
                                            .and(vueloSim2.idvuelo.eq(idVuelo2))
                                            .and(vueloSim3.idvuelo.eq(idVuelo3))
                                            .and(vueloSimX.aeropuertoSimOrigen.eq(vueloSim1.aeropuertoSimOrigen))
                                            .and(vueloSimX.aeropuertoSimDestino.eq(vueloSim2.aeropuertoSimDestino))
                                            .and(vueloSim0.llegadaest.before(vueloSimX.salidaest))
                                            .and(vueloSimX.llegadaest.before(vueloSim3.salidaest))
                                            .and(vueloSimX.numpack.add(nroPaquetes).loe(tipoAvion.cappack)))
//                                            .and(new HibernateSubQuery().from(pronostico)
//                                                    .where(pronostico.aeropuerto.eq(aeropuertoOrigen)
//                                                        .and(vuelo0.llegadaest.before(pronostico.fechareg))
//                                                        .and(pronostico.fechareg.before(vueloX.salidaest))
//                                                        .and(new HibernateSubQuery().from(pronostico2)
//                                                                .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                    .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                    .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoOrigen.cappack))).notExists())
//                                            .and(new HibernateSubQuery().from(pronostico)
//                                                    .where(pronostico.aeropuerto.eq(aeropuertoDestino)
//                                                        .and(vueloX.llegadaest.before(pronostico.fechareg))
//                                                        .and(pronostico.fechareg.before(vuelo3.salidaest))
//                                                        .and(new HibernateSubQuery().from(pronostico2)
//                                                                .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                    .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                    .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestino.cappack))).notExists()))
                                        .distinct()
                                    .list(vueloSimX);              
            
            return vuelosSim;
        }
        
        if (!(0 <= (indiceParVuelos - 1)) && (indiceParVuelos + 2) <= solucionSim.size() - 1) {
        
//            Integer idVuelo0 = solucion.get(indiceParVuelos - 1).getIdvuelo();
            Integer idVuelo3 = solucionSim.get(indiceParVuelos + 2).getIdvuelo();
            
            List<VueloSim> vuelosSim = consulta.from(vueloSimX, vueloSim1, vueloSim2, vueloSim3)
                                    .innerJoin(vueloSimX.avionSim, avionSim)
                                    .innerJoin(avionSim.tipoAvion, tipoAvion)
                                    .innerJoin(vueloSimX.aeropuertoSimOrigen, aeropuertoSimOrigen)
                                    .innerJoin(vueloSimX.aeropuertoSimDestino, aeropuertoSimDestino)
                                        .where(vueloSim1.idvuelo.eq(idVuelo1)
                                            .and(vueloSim2.idvuelo.eq(idVuelo2))
                                            .and(vueloSim3.idvuelo.eq(idVuelo3))
                                            .and(vueloSimX.aeropuertoSimOrigen.eq(vueloSim1.aeropuertoSimOrigen))
                                            .and(vueloSimX.aeropuertoSimDestino.eq(vueloSim2.aeropuertoSimDestino))
                                            .and(vueloSimX.salidaest.after(fechaPeticion))
                                            .and(vueloSimX.llegadaest.before(vueloSim3.salidaest))
                                            .and(vueloSimX.numpack.add(nroPaquetes).loe(tipoAvion.cappack)))
//                                            .and(new HibernateSubQuery().from(pronostico)
//                                                    .where(pronostico.aeropuerto.eq(aeropuertoOrigen)
//                                                        .and(pronostico.fechareg.after(fechaPeticion))
//                                                        .and(pronostico.fechareg.before(vueloX.salidaest))
//                                                        .and(new HibernateSubQuery().from(pronostico2)
//                                                                .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                    .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                    .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoOrigen.cappack))).notExists())
//                                            .and(new HibernateSubQuery().from(pronostico)
//                                                    .where(pronostico.aeropuerto.eq(aeropuertoDestino)
//                                                        .and(vueloX.llegadaest.before(pronostico.fechareg))
//                                                        .and(pronostico.fechareg.before(vuelo3.salidaest))
//                                                        .and(new HibernateSubQuery().from(pronostico2)
//                                                                .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                    .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                    .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestino.cappack))).notExists()))
                                        .distinct()
                                    .list(vueloSimX);              
            
            return vuelosSim;
            
        }
        
        if (0 <= (indiceParVuelos - 1) && !((indiceParVuelos + 2) <= solucionSim.size() - 1)) {
        
            Integer idVuelo0 = solucionSim.get(indiceParVuelos - 1).getIdvuelo();
//            Integer idVuelo3 = solucion.get(indiceParVuelos + 2).getIdvuelo();
            
            List<VueloSim> vuelosSim = consulta.from(vueloSimX, vueloSim0, vueloSim1, vueloSim2)
                                    .innerJoin(vueloSimX.avionSim, avionSim)
                                    .innerJoin(avionSim.tipoAvion, tipoAvion)
                                    .innerJoin(vueloSimX.aeropuertoSimOrigen, aeropuertoSimOrigen)
                                    .innerJoin(vueloSimX.aeropuertoSimDestino, aeropuertoSimDestino)
                                        .where(vueloSim1.idvuelo.eq(idVuelo1)
                                            .and(vueloSim2.idvuelo.eq(idVuelo2))
                                            .and(vueloSimX.aeropuertoSimOrigen.eq(vueloSim1.aeropuertoSimOrigen))
                                            .and(vueloSimX.aeropuertoSimDestino.eq(vueloSim2.aeropuertoSimDestino))
                                            .and(vueloSimX.salidaest.after(fechaPeticion))
//                                            .and(vueloX.llegadaest.before(vuelo3.salidaest))
                                            .and(vueloSimX.numpack.add(nroPaquetes).loe(tipoAvion.cappack)))
//                                            .and(new HibernateSubQuery().from(pronostico)
//                                                    .where(pronostico.aeropuerto.eq(aeropuertoOrigen)
//                                                        .and(pronostico.fechareg.after(fechaPeticion))
//                                                        .and(pronostico.fechareg.before(vueloX.salidaest))
//                                                        .and(new HibernateSubQuery().from(pronostico2)
//                                                                .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                    .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                    .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoOrigen.cappack))).notExists())
//                                            .and(new HibernateSubQuery().from(pronostico)
//                                                    .where(pronostico.aeropuerto.eq(aeropuertoDestino)
//                                                        .and(pronostico.fechareg.after(vueloX.llegadaest))
////                                                        .and(pronostico.fechareg.before(vuelo3.salidaest)) /*Arreglar*/ Tiempo retencion, politicas de despacho
//                                                        .and(new HibernateSubQuery().from(pronostico2)
//                                                                .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                    .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                    .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestino.cappack))).notExists()))
                                        .distinct()
                                    .list(vueloSimX);              
            
            return vuelosSim;
        }
        
        if (!(0 <= (indiceParVuelos - 1)) && !((indiceParVuelos + 2) <= solucionSim.size() - 1)) {
        
//            Integer idVuelo0 = solucion.get(indiceParVuelos - 1).getIdvuelo();
//            Integer idVuelo3 = solucion.get(indiceParVuelos + 2).getIdvuelo();
            
            List<VueloSim> vuelosSim = consulta.from(vueloSimX, vueloSim1, vueloSim2)
                                    .innerJoin(vueloSimX.avionSim, avionSim)
                                    .innerJoin(avionSim.tipoAvion, tipoAvion)
                                    .innerJoin(vueloSimX.aeropuertoSimOrigen, aeropuertoSimOrigen)
                                    .innerJoin(vueloSimX.aeropuertoSimDestino, aeropuertoSimDestino)
                                        .where(vueloSim1.idvuelo.eq(idVuelo1)
                                            .and(vueloSim2.idvuelo.eq(idVuelo2))
                                            .and(vueloSimX.aeropuertoSimOrigen.eq(vueloSim1.aeropuertoSimOrigen))
                                            .and(vueloSimX.aeropuertoSimDestino.eq(vueloSim2.aeropuertoSimDestino))
                                            .and(vueloSimX.salidaest.after(fechaPeticion))
//                                            .and(vueloX.llegadaest.before(vuelo3.salidaest))
                                            .and(vueloSimX.numpack.add(nroPaquetes).loe(tipoAvion.cappack)))
//                                            .and(new HibernateSubQuery().from(pronostico)
//                                                    .where(pronostico.aeropuerto.eq(aeropuertoOrigen)
//                                                        .and(pronostico.fechareg.after(fechaPeticion))
//                                                        .and(pronostico.fechareg.before(vueloX.salidaest))
//                                                        .and(new HibernateSubQuery().from(pronostico2)
//                                                                .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                    .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                    .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoOrigen.cappack))).notExists())
//                                            .and(new HibernateSubQuery().from(pronostico)
//                                                    .where(pronostico.aeropuerto.eq(aeropuertoDestino)
//                                                        .and(pronostico.fechareg.after(vueloX.llegadaest))
////                                                        .and(pronostico.fechareg.before(vuelo3.salidaest))
//                                                        .and(new HibernateSubQuery().from(pronostico2)
//                                                                .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                    .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                    .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestino.cappack))).notExists()))
                                        .distinct()
                                    .list(vueloSimX);              
            
            return vuelosSim;
        }
        
        return null;
    }//ok

    //Agregar escala
    @Override
    public List<Pair<VueloSim,VueloSim>> retornarParDeVuelosAReemplazar(ProblemaSim problemaSim, SolucionSim solucionSim, Integer indiceVuelo) {
//        throw new UnsupportedOperationException("Not supported yet.");

        JPAQuery consulta = new JPAQuery(
                                    Persistence.createEntityManagerFactory("pe.edu.pucp_motor-generador-rutas-RS2_jar_1.0-SNAPSHOTPU", System.getProperties())
                                        .createEntityManager());   
        
        QVueloSim vueloSim0 = new QVueloSim("vueloSim0");
        QVueloSim vueloSim1 = new QVueloSim("vueloSim1");
        QVueloSim vueloSim2 = new QVueloSim("vueloSim2");
        QVueloSim vueloSimX1 = new QVueloSim("vueloSimX1");
        QVueloSim vueloSimX2 = new QVueloSim("vueloSimX2");
        
        QAeropuertoSim aeropuertoSimOrigen1 = new QAeropuertoSim("aeropuertoSimOrigen1");
        QAeropuertoSim aeropuertoSimDestino1 = new QAeropuertoSim("aeropuertoSimDestino1");
        QAvionSim avionSimX1 = new QAvionSim("avionSimX1");
        QAvionSim avionSimX2 = new QAvionSim("avionSimX2"); 
        QTipoAvion tipoAvionX1 = new QTipoAvion("tipoAvionX1");
        QTipoAvion tipoAvionX2 = new QTipoAvion("tipoAvionX2");
        QAeropuertoSim aeropuertoSimDestinoX1 = new QAeropuertoSim("aeropuertoSimDestinoX1");
        QPronosticoSim pronosticoSim = QPronosticoSim.pronosticoSim;
        QPronosticoSim pronosticoSim2 = new QPronosticoSim("pronosticoSim2");
        
        
        Integer idVuelo1 = solucionSim.get(indiceVuelo).getIdvuelo();
        
        Integer nroPaquetes = problemaSim.getNroPaquetes();
        Date fechaPeticion = problemaSim.getFechaPeticion();
        
        if ( (0 <= indiceVuelo - 1) && (indiceVuelo + 1 <= solucionSim.size() - 1)) {
            
            Integer idVuelo0 = solucionSim.get(indiceVuelo - 1).getIdvuelo();
            Integer idVuelo2 = solucionSim.get(indiceVuelo + 1).getIdvuelo();            
        
            List<Object[]> listaParesDeVuelosSim = consulta.from(vueloSim0, vueloSim1, vueloSim2, vueloSimX1, vueloSimX2)
//                                                    .innerJoin(vuelo1.aeropuertoOrigen, aeropuertoOrigen1)
//                                                    .innerJoin(vuelo1.aeropuertoDestino, aeropuertoDestino1)
                                                    .innerJoin(vueloSimX1.avionSim, avionSimX1)
                                                    .innerJoin(avionSimX1.tipoAvion, tipoAvionX1)
//                                                    .innerJoin(vueloX1.aeropuertoDestino, aeropuertoDestinoX1)
                                                    .innerJoin(vueloSimX2.avionSim, avionSimX2)
                                                    .innerJoin(avionSimX2.tipoAvion, tipoAvionX2)
                                                        .where(vueloSim0.idvuelo.eq(idVuelo0)
                                                                .and(vueloSim1.idvuelo.eq(idVuelo1))
                                                                .and(vueloSim2.idvuelo.eq(idVuelo2))
                                                                .and(vueloSimX1.aeropuertoSimOrigen.eq(vueloSim1.aeropuertoSimOrigen))
                                                                .and(vueloSimX2.aeropuertoSimDestino.eq(vueloSim1.aeropuertoSimDestino))
                                                                .and(vueloSimX1.aeropuertoSimDestino.eq(vueloSimX2.aeropuertoSimOrigen))
                                                                .and(vueloSim0.llegadaest.before(vueloSimX1.salidaest))
                                                                .and(vueloSimX2.llegadaest.before(vueloSim2.salidaest))
                                                                .and(vueloSimX1.llegadaest.before(vueloSimX2.salidaest))
                                                                .and(vueloSimX1.numpack.add(nroPaquetes).loe(tipoAvionX1.cappack))
                                                                .and(vueloSimX2.numpack.add(nroPaquetes).loe(tipoAvionX2.cappack)))
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoOrigen1)
//                                                                                .and(pronostico.fechareg.after(vuelo0.llegadaest))
//                                                                                .and(pronostico.fechareg.before(vueloX1.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                        .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                            .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                            .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoOrigen1.cappack))).notExists())
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoDestino1)
//                                                                                .and(pronostico.fechareg.after(vueloX2.llegadaest))
//                                                                                .and(pronostico.fechareg.before(vuelo2.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                            .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                                .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                                .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestino1.cappack))).notExists())
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoDestinoX1)
//                                                                                .and(pronostico.fechareg.after(vueloX1.llegadaest))
//                                                                                .and(pronostico.fechareg.before(vueloX2.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                            .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                                .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                                .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestinoX1.cappack))).notExists()))
                                                    .distinct()
                                                .list(vueloSimX1, vueloSimX2);  
            
            List<Pair<VueloSim, VueloSim>> paresDeVuelosSim = new ArrayList<>();
            
            Pair<VueloSim, VueloSim> parDeVueloSim_temp = null;
            
            for(Object[] parDeVuelosSim : listaParesDeVuelosSim) {
                
                parDeVueloSim_temp = new Pair<>((VueloSim) parDeVuelosSim[0] ,(VueloSim) parDeVuelosSim[1]);
                paresDeVuelosSim.add(parDeVueloSim_temp);
            
            }
            
            
            return paresDeVuelosSim;
        }
        
        if ( !(0 <= indiceVuelo - 1) && (indiceVuelo + 1 <= solucionSim.size() - 1)) {
            
//            Integer idVuelo0 = solucion.get(indiceVuelo - 1).getIdvuelo();
            Integer idVuelo2 = solucionSim.get(indiceVuelo + 1).getIdvuelo();            
        
            List<Object[]> listaParesDeVuelosSim = consulta.from(vueloSim1, vueloSim2, vueloSimX1, vueloSimX2)
//                                                    .innerJoin(vuelo1.aeropuertoOrigen, aeropuertoOrigen1)
//                                                    .innerJoin(vuelo1.aeropuertoDestino, aeropuertoDestino1)
                                                    .innerJoin(vueloSimX1.avionSim, avionSimX1)
                                                    .innerJoin(avionSimX1.tipoAvion, tipoAvionX1)
//                                                    .innerJoin(vueloX1.aeropuertoDestino, aeropuertoDestinoX1)
                                                    .innerJoin(vueloSimX2.avionSim, avionSimX2)
                                                    .innerJoin(avionSimX2.tipoAvion, tipoAvionX2)
                                                        .where(vueloSim1.idvuelo.eq(idVuelo1)
                                                                .and(vueloSim2.idvuelo.eq(idVuelo2))
                                                                .and(vueloSimX1.aeropuertoSimOrigen.eq(vueloSim1.aeropuertoSimOrigen))
                                                                .and(vueloSimX2.aeropuertoSimDestino.eq(vueloSim1.aeropuertoSimDestino))
                                                                .and(vueloSimX1.aeropuertoSimDestino.eq(vueloSimX2.aeropuertoSimOrigen))
                                                                .and(vueloSimX1.salidaest.after(fechaPeticion))
                                                                .and(vueloSimX2.llegadaest.before(vueloSim2.salidaest))
                                                                .and(vueloSimX1.llegadaest.before(vueloSimX2.salidaest))
                                                                .and(vueloSimX1.numpack.add(nroPaquetes).loe(tipoAvionX1.cappack))
                                                                .and(vueloSimX2.numpack.add(nroPaquetes).loe(tipoAvionX2.cappack)))
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoOrigen1)
//                                                                                .and(pronostico.fechareg.after(fechaPeticion))
//                                                                                .and(pronostico.fechareg.before(vueloX1.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                        .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                            .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                            .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoOrigen1.cappack))).notExists())
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoDestino1)
//                                                                                .and(pronostico.fechareg.after(vueloX2.llegadaest))
//                                                                                .and(pronostico.fechareg.before(vuelo2.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                            .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                                .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                                .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestino1.cappack))).notExists())
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoDestinoX1)
//                                                                                .and(pronostico.fechareg.after(vueloX1.llegadaest))
//                                                                                .and(pronostico.fechareg.before(vueloX2.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                            .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                                .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                                .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestinoX1.cappack))).notExists()))
                                                    .distinct()
                                                .list(vueloSimX1, vueloSimX2);  
            
            List<Pair<VueloSim, VueloSim>> paresDeVuelosSim = new ArrayList<>();
            
            Pair<VueloSim, VueloSim> parDeVueloSim_temp = null;
            
            for(Object[] parDeVuelosSim : listaParesDeVuelosSim) {
                
                parDeVueloSim_temp = new Pair<>((VueloSim) parDeVuelosSim[0] ,(VueloSim) parDeVuelosSim[1]);
                paresDeVuelosSim.add(parDeVueloSim_temp);
            
            }
            
            
            return paresDeVuelosSim;
        }
        
        if ( (0 <= indiceVuelo - 1) && !(indiceVuelo + 1 <= solucionSim.size() - 1)) {
            
            Integer idVuelo0 = solucionSim.get(indiceVuelo - 1).getIdvuelo();
//            Integer idVuelo2 = solucion.get(indiceVuelo + 1).getIdvuelo();            
        
            List<Object[]> listaParesDeVuelosSim = consulta.from(vueloSim0, vueloSim1, vueloSimX1, vueloSimX2)
//                                                    .innerJoin(vuelo1.aeropuertoOrigen, aeropuertoOrigen1)
//                                                    .innerJoin(vuelo1.aeropuertoDestino, aeropuertoDestino1)
                                                    .innerJoin(vueloSimX1.avionSim, avionSimX1)
                                                    .innerJoin(avionSimX1.tipoAvion, tipoAvionX1)
//                                                    .innerJoin(vueloX1.aeropuertoDestino, aeropuertoDestinoX1)
                                                    .innerJoin(vueloSimX2.avionSim, avionSimX2)
                                                    .innerJoin(avionSimX2.tipoAvion, tipoAvionX2)
                                                        .where(vueloSim0.idvuelo.eq(idVuelo0)
                                                                .and(vueloSim1.idvuelo.eq(idVuelo1))
//                                                                .and(vuelo2.idvuelo.eq(idVuelo2))
                                                                .and(vueloSimX1.aeropuertoSimOrigen.eq(vueloSim1.aeropuertoSimOrigen))
                                                                .and(vueloSimX2.aeropuertoSimDestino.eq(vueloSim1.aeropuertoSimDestino))
                                                                .and(vueloSimX1.aeropuertoSimDestino.eq(vueloSimX2.aeropuertoSimOrigen))
                                                                .and(vueloSim0.llegadaest.before(vueloSimX1.salidaest))
//                                                                .and(vueloX2.llegadaest.before(vuelo2.salidaest))
                                                                .and(vueloSimX1.llegadaest.before(vueloSimX2.salidaest))
                                                                .and(vueloSimX1.numpack.add(nroPaquetes).loe(tipoAvionX1.cappack))
                                                                .and(vueloSimX2.numpack.add(nroPaquetes).loe(tipoAvionX2.cappack)))
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoOrigen1)
//                                                                                .and(pronostico.fechareg.after(vuelo0.llegadaest))
//                                                                                .and(pronostico.fechareg.before(vueloX1.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                        .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                            .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                            .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoOrigen1.cappack))).notExists())
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoDestino1)
//                                                                                .and(pronostico.fechareg.after(vueloX2.llegadaest))
////                                                                                .and(pronostico.fechareg.before(vuelo2.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                            .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                                .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                                .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestino1.cappack))).notExists())
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoDestinoX1)
//                                                                                .and(pronostico.fechareg.after(vueloX1.llegadaest))
//                                                                                .and(pronostico.fechareg.before(vueloX2.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                            .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                                .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                                .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestinoX1.cappack))).notExists()))
                                                    .distinct()
                                                .list(vueloSimX1, vueloSimX2);  
            
            List<Pair<VueloSim, VueloSim>> paresDeVuelosSim = new ArrayList<>();
            
            Pair<VueloSim, VueloSim> parDeVueloSim_temp = null;
            
            for(Object[] parDeVuelosSim : listaParesDeVuelosSim) {
                
                parDeVueloSim_temp = new Pair<>((VueloSim) parDeVuelosSim[0] ,(VueloSim) parDeVuelosSim[1]);
                paresDeVuelosSim.add(parDeVueloSim_temp);
            
            }
            
            
            return paresDeVuelosSim;
        }
       
        if ( !(0 <= indiceVuelo - 1) && !(indiceVuelo + 1 <= solucionSim.size() - 1)) {
            
//            Integer idVuelo0 = solucion.get(indiceVuelo - 1).getIdvuelo();
//            Integer idVuelo2 = solucion.get(indiceVuelo + 1).getIdvuelo();            
        
            List<Object[]> listaParesDeVuelosSim = consulta.from(vueloSim0, vueloSim1, vueloSim2, vueloSimX1, vueloSimX2)
//                                                    .innerJoin(vuelo1.aeropuertoOrigen, aeropuertoOrigen1)
//                                                    .innerJoin(vuelo1.aeropuertoDestino, aeropuertoDestino1)
                                                    .innerJoin(vueloSimX1.avionSim, avionSimX1)
                                                    .innerJoin(avionSimX1.tipoAvion, tipoAvionX1)
//                                                    .innerJoin(vueloX1.aeropuertoDestino, aeropuertoDestinoX1)
                                                    .innerJoin(vueloSimX2.avionSim, avionSimX2)
                                                    .innerJoin(avionSimX2.tipoAvion, tipoAvionX2)
                                                        .where(vueloSim1.idvuelo.eq(idVuelo1)
//                                                                .and(vuelo2.idvuelo.eq(idVuelo2))
                                                                .and(vueloSimX1.aeropuertoSimOrigen.eq(vueloSim1.aeropuertoSimOrigen))
                                                                .and(vueloSimX2.aeropuertoSimDestino.eq(vueloSim1.aeropuertoSimDestino))
                                                                .and(vueloSimX1.aeropuertoSimDestino.eq(vueloSimX2.aeropuertoSimOrigen))
                                                                .and(vueloSimX1.salidaest.after(fechaPeticion))
//                                                                .and(vueloX2.llegadaest.before(vuelo2.salidaest))
                                                                .and(vueloSimX1.llegadaest.before(vueloSimX2.salidaest))
                                                                .and(vueloSimX1.numpack.add(nroPaquetes).loe(tipoAvionX1.cappack))
                                                                .and(vueloSimX2.numpack.add(nroPaquetes).loe(tipoAvionX2.cappack)))
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoOrigen1)
//                                                                                .and(pronostico.fechareg.after(fechaPeticion))
//                                                                                .and(pronostico.fechareg.before(vueloX1.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                        .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                            .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                            .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoOrigen1.cappack))).notExists())
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoDestino1)
//                                                                                .and(pronostico.fechareg.after(vueloX2.llegadaest))
////                                                                                .and(pronostico.fechareg.before(vuelo2.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                            .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                                .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                                .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestino1.cappack))).notExists())
//                                                                .and(new HibernateSubQuery().from(pronostico)
//                                                                            .where(pronostico.aeropuerto.eq(aeropuertoDestinoX1)
//                                                                                .and(pronostico.fechareg.after(vueloX1.llegadaest))
//                                                                                .and(pronostico.fechareg.before(vueloX2.salidaest))
//                                                                                .and(new HibernateSubQuery().from(pronostico2)
//                                                                                            .where(pronostico2.aeropuerto.eq(pronostico.aeropuerto)
//                                                                                                .and(pronostico2.fechareg.before(pronostico.fechareg)))
//                                                                                                .unique(pronostico2.nropack.sum()).add(nroPaquetes).gt(aeropuertoDestinoX1.cappack))).notExists()))
                                                    .distinct()
                                                .list(vueloSimX1, vueloSimX2);  
            
            List<Pair<VueloSim, VueloSim>> paresDeVuelosSim = new ArrayList<>();
            
            Pair<VueloSim, VueloSim> parDeVueloSim_temp = null;
            
            for(Object[] parDeVuelosSim : listaParesDeVuelosSim) {
                
                parDeVueloSim_temp = new Pair<>((VueloSim) parDeVuelosSim[0] ,(VueloSim) parDeVuelosSim[1]);
                paresDeVuelosSim.add(parDeVueloSim_temp);
            
            }
            
            
            return paresDeVuelosSim;
        }
        
        return null;
        
    }
    
}
